package com.winding.plugin.swagger;

import com.google.common.collect.Maps;
import com.thoughtworks.qdox.model.JavaClass;
import com.winding.plugin.swagger.entity.SwaggerDoc;
import com.winding.plugin.swagger.entity.WrapSwagger;
import com.winding.plugin.swagger.utils.JavaSourceUtils;
import com.winding.plugin.swagger.utils.SourceReader;
import io.swagger.models.Swagger;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>TODO
 *
 * @author wind
 * @version 1.0
 * @since 2018/12/5
 */
@Slf4j
public class SwaggerSourceParse {

    private SwaggerDoc swaggerDoc;

    private ClassLoader classLoader;

    public SwaggerSourceParse(SwaggerDoc swaggerDoc, ClassLoader classLoader) {
        this.swaggerDoc = swaggerDoc;
        this.classLoader = classLoader;
    }

    private static final String DEFAULT_DIR = "target";

    public WrapSwagger parseJarSource() {
        String sourceDir = DEFAULT_DIR;
        if (StringUtils.isNoneBlank(swaggerDoc.getSourceDir())) {
            sourceDir = swaggerDoc.getSourceDir();
        }
        File file = null;
        if (swaggerDoc.isUseWar()) {
            try {
                file = new ClassPathResource(sourceDir).getFile();
                log.info("read file path is {}", file.getAbsolutePath());
            } catch (Exception e) {
                log.warn("", e);
                file = new File(sourceDir);
                log.info("read file path is {}", file.getAbsolutePath());

            }
        } else if (!swaggerDoc.isUseProjectFile()) {
            file = new File(sourceDir);
            log.info("read file path is {}", file.getAbsolutePath());
        }
        List<JavaClass> javaClassList = new ArrayList<>();
        Map<String, JavaClass> projectJavaClassMap = Maps.newHashMap();
        if (file != null) {
            File[] files = file.listFiles();

            if (files != null) {
                for (File file1 : files) {
                    if (file1.isDirectory()) {
                        continue;
                    }
                    try {
                        if (file1.getName().lastIndexOf("sources.jar") < 0) {
                            continue;
                        }
                        List<JavaClass> list = SourceReader.readFile(file1);
                        javaClassList.addAll(list);
                    } catch (IOException e) {
                        log.warn("SourceReader.readFile error");
                    }
                }
            }
            log.info("list javaClassList size:{}", javaClassList.size());
        }
        if (swaggerDoc.isUseProjectFile()) {
            List<File> projectFiles = JavaSourceUtils.listProjectJavaFile();
            log.info("list projectFiles size:{}", projectFiles.size());
            try {
                Map<String, JavaClass> javaClassMap = SourceReader
                        .transForJavaClass(SourceReader.readJavaFiles(projectFiles));
                if (javaClassMap != null) {
                    projectJavaClassMap.putAll(javaClassMap);
                }
            } catch (IOException e) {
                log.warn("SourceReader.transForJavaClass error ");
            }

        }
        Map<String, JavaClass> javaClassMap = SourceReader.transForJavaClass(javaClassList);
        if (javaClassMap != null) {
            projectJavaClassMap.putAll(javaClassMap);
        }
        Swagger swagger = new SwaggerDocReader(swaggerDoc, new Swagger(), classLoader).read(projectJavaClassMap);
        WrapSwagger wrapSwagger = new WrapSwagger();
        BeanUtils.copyProperties(swagger, wrapSwagger);
        wrapSwagger.process();
        return wrapSwagger;
    }

}
